package javagprssrv.DataBase;

import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import java.util.Enumeration;
import java.sql.DriverManager;
import java.sql.Connection;
import javagprssrv.JGS_Param;
import java.util.Vector;
import javagprssrv.StructClass.structDBInfo;

public class DBConnectionPool
{
    private boolean isError;
    private javagprssrv.StructClass.structDBInfo DBInfo;
    private java.lang.String DBConnection_URL;
    private int MinPoolSize;
    private int MaxPoolSize;
    private int incrementalConnections;
    private int TotalPoolSize;
    public java.util.Vector ConnectionPool;
    private java.lang.String testTable;
    public final Vector StatementPool = new Vector();
    
    public DBConnectionPool(final javagprssrv.StructClass.structDBInfo _DBInfo) {
        this.isError = false;
        this.DBInfo = new javagprssrv.StructClass.structDBInfo();
        this.DBConnection_URL = "";
        this.MinPoolSize = -1;
        this.MaxPoolSize = -1;
        this.incrementalConnections = 5;
        this.TotalPoolSize = 0;
        this.ConnectionPool = new java.util.Vector();
        this.testTable = "test";
        this.DBInfo = _DBInfo;
        this.MinPoolSize = _DBInfo.DB_ConnectionPoolSize_Min;
        this.MaxPoolSize = _DBInfo.DB_ConnectionPoolSize_Max;
        this.InitDBConnectionPool(this.DBInfo.DB_IsUse);
    }
    
    private void LoadDBClass() {
        java.lang.String DBClassString = "";
        if (this.DBInfo.DB_Type == 0) {
            DBClassString = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        }
        if (this.DBInfo.DB_Type == 1) {
            DBClassString = "oracle.jdbc.driver.OracleDriver";
        }
        if (this.DBInfo.DB_Type == 2) {
            DBClassString = "";
        }
        if (this.DBInfo.DB_Type == 3) {
            DBClassString = "";
        }
        if (this.DBInfo.DB_Type == 4) {
            DBClassString = "sun.jdbc.odbc.JdbcOdbcDriver";
        }
        try {
            java.lang.Class.forName(DBClassString).newInstance();
        }
        catch (java.lang.Exception e) {
            this.isError = true;
            javagprssrv.JGS_Param.myLog.ShowLog("数据库连接池初始化失败(DBConnectionPool.InitDBConnectionPool())。", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
            return;
        }
        if (this.DBInfo.DB_Type == 0) {
            this.DBConnection_URL = "jdbc:sqlserver://" + this.DBInfo.DB_ServerIP + ":" + this.DBInfo.DB_ServerPort + ";DatabaseName=" + this.DBInfo.DB_ServerName;
        }
        if (this.DBInfo.DB_Type == 1) {
            this.DBConnection_URL = "jdbc:oracle:thin:@" + this.DBInfo.DB_ServerIP + ":" + this.DBInfo.DB_ServerPort + ":" + this.DBInfo.DB_ServerName;
        }
        if (this.DBInfo.DB_Type == 2) {
            this.DBConnection_URL = "";
        }
        if (this.DBInfo.DB_Type == 3) {
            this.DBConnection_URL = "";
        }
        if (this.DBInfo.DB_Type == 4) {
            this.DBConnection_URL = "jdbc:odbc:" + this.DBInfo.DB_ServerName;
        }
    }
    
    public void InitDBConnectionPool(final int _DB_isUse) {
        if (_DB_isUse == 0) {
            javagprssrv.JGS_Param.myLog.ShowLog("系统不应用数据库，这里不建立数据连接池。", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
            return;
        }
        this.LoadDBClass();
        int ErrorTimes = 0;
        for (int i = 0; i < this.MinPoolSize; ++i) {
            try {
                final java.sql.Connection conn = this.NewConnection();
                this.ConnectionPool.addElement(new javagprssrv.DataBase.DBConnectionPool.PooledConnection(conn));
            }
            catch (java.lang.Exception e) {
                ++ErrorTimes;
                javagprssrv.JGS_Param.myLog.ShowLog("数据库连接失败 ( " + java.lang.String.valueOf(i + 1) + " / " + java.lang.String.valueOf(this.MinPoolSize) + " ) 。", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
            }
        }
        if (ErrorTimes == this.MinPoolSize) {
            final java.lang.String s = "数据库连接池创建 全部失败 ！！！原因可能为“网络故障”或者“数据库服务器故障”，请确认。";
            javagprssrv.JGS_Param.myLog.ShowLog(s, java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
        }
        else {
            final java.lang.String s = "数据库连接池创建完毕。( 成功 ： " + java.lang.String.valueOf(this.MinPoolSize - ErrorTimes) + " ，失败 ： " + java.lang.String.valueOf(ErrorTimes) + " )";
            javagprssrv.JGS_Param.myLog.ShowLog(s, java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
        }
    }
    
    public java.sql.Connection NewConnection() {
        java.sql.Connection conn = null;
        try {
            conn = java.sql.DriverManager.getConnection(this.DBConnection_URL, this.DBInfo.DB_ServerUserName, this.DBInfo.DB_ServerUserPass);
            javagprssrv.JGS_Param.myLog.ShowLog("创建了一个新的连接:" + this.ConnectionPool.size(), java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
        }
        catch (java.lang.Exception e) {
            javagprssrv.JGS_Param.myLog.ShowLog("不能创建数据库连接:" + this.DBConnection_URL, java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
        }
        return conn;
    }
    
    public synchronized java.sql.Connection UseConnection() {
        if (this.ConnectionPool == null) {
            return null;
        }
        java.sql.Connection conn;
        for (conn = this.getFreeConnection(); conn == null; conn = this.getFreeConnection()) {
            try {
                this.wait(250);
            }
            catch (java.lang.InterruptedException ex) {
                javagprssrv.JGS_Param.myLog.ShowLog("等待一会儿获取连接睡眠被中断", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
            }
        }
        javagprssrv.JGS_Param.myLog.ShowLog("线程" + java.lang.Thread.currentThread().getName() + "使用一个连接" + conn, java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
        return conn;
    }
    
    private java.sql.Connection getFreeConnection() {
        java.sql.Connection conn = this.findFreeConnection();
        if (conn == null) {
            this.createConnections(this.incrementalConnections);
            conn = this.findFreeConnection();
            if (conn == null) {
                return null;
            }
        }
        return conn;
    }
    
    private void createConnections(final int numConnections) {
        for (int x = 0; x < numConnections && (this.MaxPoolSize <= 0 || this.ConnectionPool.size() < this.MaxPoolSize); ++x) {
            this.ConnectionPool.addElement(new javagprssrv.DataBase.DBConnectionPool.PooledConnection(this.NewConnection()));
            javagprssrv.JGS_Param.myLog.ShowLog("新创建连接" + numConnections + "个，目前共" + this.ConnectionPool.size() + "个链接", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
            java.lang.System.out.println(" 数据库连接己创建 ......");
        }
    }
    
    private java.sql.Connection findFreeConnection() {
        java.sql.Connection conn = null;
        javagprssrv.DataBase.DBConnectionPool.PooledConnection pConn = null;
        final java.util.Enumeration enumerate = this.ConnectionPool.elements();
        while (enumerate.hasMoreElements()) {
            pConn = (PooledConnection) enumerate.nextElement();
            if (!pConn.isBusy()) {
                conn = pConn.getConnection();
                pConn.setBusy(true);
                if (!this.testConnection(conn)) {
                    conn = this.NewConnection();
                    pConn.setConnection(conn);
                    break;
                }
                break;
            }
        }
        return conn;
    }
    
    private boolean testConnection(final java.sql.Connection conn) {
        try {
            if (this.testTable.equals("")) {
                conn.setAutoCommit(true);
            }
            else {
                final java.sql.Statement stmt = conn.createStatement();
                final java.sql.ResultSet rs = stmt.executeQuery("select count(*) from " + this.testTable);
                rs.next();
            }
        }
        catch (java.sql.SQLException e) {
            e.printStackTrace();
            this.closeConnection(conn);
            return false;
        }
        return true;
    }
    
    public synchronized void closeConnectionPool() throws java.sql.SQLException {
        if (this.ConnectionPool == null) {
            java.lang.System.out.println(" 连接池不存在，无法关闭 !");
            return;
        }
        javagprssrv.DataBase.DBConnectionPool.PooledConnection pConn = null;
        final java.util.Enumeration enumerate = this.ConnectionPool.elements();
        while (enumerate.hasMoreElements()) {
            pConn = (PooledConnection) enumerate.nextElement();
            if (pConn.isBusy()) {
                try {
                    this.wait(5000);
                }
                catch (java.lang.InterruptedException ex) {
                    javagprssrv.JGS_Param.myLog.ShowLog("等待5秒关闭连接被中断", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
                }
            }
            this.closeConnection(pConn.getConnection());
            this.ConnectionPool.removeElement(pConn);
        }
        this.ConnectionPool = null;
    }
    
    private void closeConnection(final java.sql.Connection conn) {
        try {
            conn.close();
        }
        catch (java.sql.SQLException e) {
            java.lang.System.out.println(" 关闭数据库连接出错： " + e.getMessage());
        }
    }
    
    private void wait(final int mSeconds) throws java.lang.InterruptedException {
        java.lang.Thread.sleep(mSeconds);
    }
    
    public void UnUseConnection(final java.sql.Connection conn) {
        if (this.ConnectionPool == null) {
            java.lang.System.out.println(" 连接池不存在，无法返回此连接到连接池中 !");
            return;
        }
        javagprssrv.DataBase.DBConnectionPool.PooledConnection pConn = null;
        final java.util.Enumeration enumerate = this.ConnectionPool.elements();
        while (enumerate.hasMoreElements()) {
            pConn = (PooledConnection) enumerate.nextElement();
            if (conn == pConn.getConnection()) {
                javagprssrv.JGS_Param.myLog.ShowLog("线程" + java.lang.Thread.currentThread().getName() + "归还一个连接" + conn, java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
                pConn.setBusy(false);
                break;
            }
        }
    }
    
    public synchronized void refreshConnections() throws java.sql.SQLException {
        if (this.ConnectionPool == null) {
            java.lang.System.out.println(" 连接池不存在，无法刷新 !");
            return;
        }
        javagprssrv.DataBase.DBConnectionPool.PooledConnection pConn = null;
        final java.util.Enumeration enumerate = this.ConnectionPool.elements();
        while (enumerate.hasMoreElements()) {
            pConn = (PooledConnection) enumerate.nextElement();
            if (pConn.isBusy()) {
                try {
                    this.wait(5000);
                }
                catch (java.lang.InterruptedException ex) {
                    javagprssrv.JGS_Param.myLog.ShowLog("等待5秒刷新连接被中断", java.lang.Boolean.TRUE, java.lang.Boolean.TRUE);
                }
            }
            this.closeConnection(pConn.getConnection());
            pConn.setConnection(this.NewConnection());
            pConn.setBusy(false);
        }
    }
    
    class PooledConnection
    {
        java.sql.Connection connection;
        boolean busy;
        
        public PooledConnection(final java.sql.Connection connection) {
            this.connection = null;
            this.busy = false;
            this.connection = connection;
        }
        
        public java.sql.Connection getConnection() {
            return this.connection;
        }
        
        public void setConnection(final java.sql.Connection connection) {
            this.connection = connection;
        }
        
        public boolean isBusy() {
            return this.busy;
        }
        
        public void setBusy(final boolean busy) {
            this.busy = busy;
        }
    }
}
